package com.letoken.platform.app.service.impl;

import com.letoken.platform.app.service.AppBalanceService;
import com.letoken.platform.app.service.AppUserWalletService;
import com.letoken.platform.pub.constant.ConstantsValue;
import com.letoken.platform.pub.enums.*;
import com.letoken.platform.pub.exception.ApiServiceException;
import com.letoken.platform.repo.app.dao.AppBalanceHistoryMapper;
import com.letoken.platform.repo.app.dao.AppBalanceWalletMapper;
import com.letoken.platform.repo.app.dao.AppUserAssetsHistoryMapper;
import com.letoken.platform.repo.app.dao.AppUserWalletMapper;
import com.letoken.platform.repo.app.po.AppUserAssetsHistory;
import com.letoken.platform.repo.app.po.AppUserWallet;
import com.letoken.platform.repo.app.req.user.BalanceTransferReq;
import com.letoken.platform.repo.app.res.user.AppBalanceRes;
import com.letoken.platform.repo.mall.po.AppBalanceHistory;
import com.letoken.platform.repo.mall.po.AppBalanceWallet;
import com.letoken.platform.repo.utlis.UniqueIDUtils;
import com.letoken.platform.repo.utlis.WebUtils;
import com.letoken.platform.repo.utlis.lock.Lock;
import com.letoken.platform.repo.utlis.lock.LockCategoryEnum;
import io.reactivex.Observable;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;

@Service
@Log4j2
public class AppBalanceServiceImpl implements AppBalanceService {
    @Autowired
    AppBalanceWalletMapper appBalanceWalletMapper;
    @Autowired
    AppBalanceHistoryMapper appBalanceHistoryMapper;
    @Autowired
    AppUserWalletMapper appUserWalletMapper;
    @Autowired
    AppUserAssetsHistoryMapper appUserAssetsHistoryMapper;


    @Autowired
    AppUserWalletService appUserWalletService;


    @Override
    @Lock(ce = LockCategoryEnum.USER_ID,value = "CREATE:RECORD",expire = 3l)
    public AppBalanceRes createRecord(){
        Integer userId = WebUtils.getUserId();
        AppBalanceWallet w = appBalanceWalletMapper.getRecord(userId, LetokenTokenTypeEnum.LET.getId());
        AppBalanceRes res = new AppBalanceRes();
        if (ObjectUtils.isEmpty(w)){
            w = new AppBalanceWallet();
            w.setTokenId(LetokenTokenTypeEnum.LET.getId());
            w.setUserId(userId);
            appBalanceWalletMapper.insert(w);
            res.setIsNew(ConstantsValue.TRUE);
        }
        BeanUtils.copyProperties(w,res);
        return res;
    }

    @Override
    @Transactional
    // 钱包 --> 余额宝
    @Lock(ce = LockCategoryEnum.USER_ID,value = "BALANCE:TRANSFER",expire = 3l)
    public void transferIn(BalanceTransferReq req) {
        AppUserWallet w = appUserWalletMapper.selectForUpdate(req.getWalletId());
        AppBalanceWallet b = appBalanceWalletMapper.selectForUpdate(req.getBalanceId());
        if (w.getAvailableBalance().compareTo(req.getAmount()) < 0){
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_MALL_SMS_052);
        }
        if (b.getBalance().compareTo(BigDecimal.ZERO) < 0){
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_MALL_SMS_053);
        }


        AppBalanceWallet updateB = new AppBalanceWallet();
        updateB.setId(req.getBalanceId());
        updateB.setBalance(b.getBalance().add(req.getAmount()));
        appBalanceWalletMapper.updateById(updateB);

        String seqNo = UniqueIDUtils.genSeqNo("BA");
        appUserWalletService.updateWallet(LetokenTokenTypeEnum.LET.getId(), req.getUserId(),req.getAmount().negate(),TokenTransactionTypeEnum.TRANSFER_OUT_BALANCE.getValue(),seqNo);


        /*AppUserWallet updateW = new AppUserWallet();
        updateW.setId(w.getId());
        updateW.setAvailableBalance(w.getAvailableBalance().subtract(req.getAmount()));
        appUserWalletMapper.updateById(updateW);
        AppUserAssetsHistory assetHistory = new AppUserAssetsHistory();
        assetHistory.setUserId(req.getUserId());
        assetHistory.setType(TokenTransactionTypeEnum.TRANSFER_OUT_BALANCE.getValue());
        assetHistory.setStatus(TokenTransactionStatusEnum.COMPLETED.getValue());
        assetHistory.setTokenId(LetokenTokenTypeEnum.LET.getId());
        assetHistory.setAmount(req.getAmount().negate());
        assetHistory.setSn(seqNo);
        assetHistory.setBalance(updateW.getAvailableBalance());
        assetHistory.setCreateTime(LocalDateTime.now());
        assetHistory.setUpdateTime(assetHistory.getCreateTime());
        appUserAssetsHistoryMapper.insert(assetHistory);*/


        AppBalanceHistory abh = new AppBalanceHistory();
        abh.setBalance(updateB.getBalance());
        abh.setAmount(req.getAmount());
        abh.setType(BalanceTypeEnum.TRANSFER_IN.ordinal());
        abh.setInOut(InOutTypeEnum.IN.ordinal());
        abh.setSeqNo(seqNo);
        abh.setTokenId(LetokenTokenTypeEnum.LET.getId());
        abh.setUserId(req.getUserId());
        appBalanceHistoryMapper.insert(abh);

    }


    @Override
    @Transactional
    // 余额宝--> 钱包
    @Lock(ce = LockCategoryEnum.USER_ID,value = "BALANCE:TRANSFER",expire = 3l)
    public void transferOut(BalanceTransferReq req) {

        AppBalanceWallet b = appBalanceWalletMapper.selectForUpdate(req.getBalanceId());
        AppUserWallet w = appUserWalletMapper.selectForUpdate(req.getWalletId());
        if (b.getBalance().compareTo(req.getAmount()) < 0){
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_MALL_SMS_052);
        }
        if (w.getAvailableBalance().compareTo(BigDecimal.ZERO) < 0){
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_MALL_SMS_053);
        }

        AppBalanceWallet updateB = new AppBalanceWallet();
        updateB.setId(req.getBalanceId());
        updateB.setBalance(b.getBalance().subtract(req.getAmount()));
        appBalanceWalletMapper.updateById(updateB);



        String seqNo = UniqueIDUtils.genSeqNo("AB");
        appUserWalletService.updateWallet(LetokenTokenTypeEnum.LET.getId(), req.getUserId(),req.getAmount(),TokenTransactionTypeEnum.TRANSFER_IN_BALANCE.getValue(),seqNo);


        /*AppUserWallet updateW = new AppUserWallet();
        updateW.setId(w.getId());
        updateW.setAvailableBalance(w.getAvailableBalance().add(req.getAmount()));
        appUserWalletMapper.updateById(updateW);

        AppUserAssetsHistory assetHistory = new AppUserAssetsHistory();
        assetHistory.setUserId(req.getUserId());
        assetHistory.setType(TokenTransactionTypeEnum.TRANSFER_IN_BALANCE.getValue());
        assetHistory.setStatus(TokenTransactionStatusEnum.COMPLETED.getValue());
        assetHistory.setTokenId(LetokenTokenTypeEnum.LET.getId());
        assetHistory.setAmount(req.getAmount());
        assetHistory.setSn(seqNo);
        assetHistory.setBalance(updateW.getAvailableBalance());
        assetHistory.setCreateTime(LocalDateTime.now());
        assetHistory.setUpdateTime(assetHistory.getCreateTime());
        appUserAssetsHistoryMapper.insert(assetHistory);*/


        AppBalanceHistory abh = new AppBalanceHistory();
        abh.setBalance(updateB.getBalance());
        abh.setAmount(req.getAmount().negate());
        abh.setType(BalanceTypeEnum.TRANSFER_OUT.ordinal());
        abh.setInOut(InOutTypeEnum.OUT.ordinal());
        abh.setSeqNo(seqNo);
        abh.setTokenId(LetokenTokenTypeEnum.LET.getId());
        abh.setUserId(req.getUserId());
        appBalanceHistoryMapper.insert(abh);
    }
}
